package com.hsurosy.domain.activity.service.quota;

import com.alibaba.fastjson.JSON;
import com.hsurosy.domain.activity.model.aggregate.CreateQuotaOrderAggregate;
import com.hsurosy.domain.activity.model.entity.*;
import com.hsurosy.domain.activity.model.valobj.OrderTradeTypeVO;
import com.hsurosy.domain.activity.repository.IActivityRepository;
import com.hsurosy.domain.activity.service.IRaffleActivityAccountQuotaService;
import com.hsurosy.domain.activity.service.quota.policy.ITradePolicy;
import com.hsurosy.domain.activity.service.quota.rule.IActionChain;
import com.hsurosy.domain.activity.service.quota.rule.factory.DefaultActivityChainFactory;
import com.hsurosy.types.enums.ResponseCode;
import com.hsurosy.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Map;

/**
 * @Author Hsu琛君珩
 * @Date 2024-11-04 17:29
 * @Description 抽奖活动抽象类，定义标准的流程
 * @Version: v1.0.0
 */
@Slf4j
public abstract class AbstractRaffleActivityAccountQuota extends RaffleActivityAccountQuotaSupport implements IRaffleActivityAccountQuotaService {

    private final Map<String, ITradePolicy> tradePolicyGroup; // 交易策略分组

    public AbstractRaffleActivityAccountQuota(DefaultActivityChainFactory defaultActivityChainFactory, IActivityRepository activityRepository, Map<String, ITradePolicy> tradePolicyGroup) {
        super(defaultActivityChainFactory, activityRepository);
        this.tradePolicyGroup = tradePolicyGroup;
    }

    /**
     * 创建抽奖活动订单，根据购物车中的 SKU 查询对应的活动信息和参与次数信息，并返回构建的订单实体
     *
     * @param activityShopCartEntity 包含SKU的活动购物车实体
     * @return 构建的活动订单实体对象
     */
    @Override
    public ActivityOrderEntity createRaffleActivityOrder(ActivityShopCartEntity activityShopCartEntity) {
        // 1. 通过sku查询活动信息
        ActivitySkuEntity activitySkuEntity = activityRepository.queryActivitySku(activityShopCartEntity.getSku());
        // 2. 查询活动信息
        ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
        // 3. 查询次数信息（用户在活动中可参与的次数）
        ActivityCountEntity activityCountEntity = activityRepository.queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());

        log.info("查询结果：{} {} {}", JSON.toJSONString(activitySkuEntity), JSON.toJSONString(activityEntity), JSON.toJSONString(activityCountEntity));

        return ActivityOrderEntity.builder().build();
    }

    /**
     * 创建SKU充值订单
     *
     * @param skuRechargeEntity SKU充值信息实体，包含用户ID、SKU、业务流水号等信息
     * @return 未支付的活动订单信息
     * @throws AppException 如果参数不合法或其他异常场景
     */
    @Override
    public UnpaidActivityOrderEntity createOrder(SkuRechargeEntity skuRechargeEntity) {
        // 1. 参数校验
        String userId = skuRechargeEntity.getUserId();
        Long sku = skuRechargeEntity.getSku();
        String outBusinessNo = skuRechargeEntity.getOutBusinessNo();
        // 检查用户ID、SKU、外部业务号是否为空，若为空则抛出参数非法异常
        if (null == sku || StringUtils.isBlank(userId) || StringUtils.isBlank(outBusinessNo)) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        // 2. 查询未支付订单「一个月以内的未支付订单」
        UnpaidActivityOrderEntity unpaidCreditOrder = activityRepository.queryUnpaidActivityOrder(skuRechargeEntity);
        if (null != unpaidCreditOrder) {
            return unpaidCreditOrder; // 如果存在未支付订单，则直接返回，避免重复创建
        }

        // 3. 查询基础信息：获取活动、SKU、用户活动次数等必要信息
        // 3.1 通过 SKU 查询活动 SKU 信息
        ActivitySkuEntity activitySkuEntity = queryActivitySku(sku);
        // 3.2 查询活动信息，根据活动 ID 获取相关信息
        ActivityEntity activityEntity = queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
        // 3.3 查询用户的活动次数信息（可参与的总次数、日次数、月次数等）
        ActivityCountEntity activityCountEntity = queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());

        // 4. 账户额度校验：针对信用支付交易类型，检查用户信用账户余额是否足够
        if (OrderTradeTypeVO.credit_pay_trade.equals(skuRechargeEntity.getOrderTradeType())){
            // 查询用户信用账户的可用余额
            BigDecimal availableAmount = activityRepository.queryUserCreditAccountAmount(userId);
            // 如果用户信用账户余额不足以支付当前SKU金额，则抛出余额不足异常
            if (availableAmount.compareTo(activitySkuEntity.getProductAmount()) < 0) {
                throw new AppException(ResponseCode.USER_CREDIT_ACCOUNT_NO_AVAILABLE_AMOUNT.getCode(), ResponseCode.USER_CREDIT_ACCOUNT_NO_AVAILABLE_AMOUNT.getInfo());
            }
        }

        // 5. 活动动作规则校验。通过责任链进行规则校验，以验证用户是否符合活动参与规则
        IActionChain actionChain = defaultActivityChainFactory.openActionChain();
        actionChain.action(activitySkuEntity, activityEntity, activityCountEntity);

        // 6. 构建订单聚合对象。根据充值实体、活动 SKU、活动信息和次数信息，构建订单的聚合对象，便于后续操作
        CreateQuotaOrderAggregate createOrderAggregate = buildOrderAggregate(skuRechargeEntity, activitySkuEntity, activityEntity, activityCountEntity);

        // 7. 保存订单，根据交易类型选择对应的策略，并调用其交易逻辑
        ITradePolicy tradePolicy = tradePolicyGroup.get(skuRechargeEntity.getOrderTradeType().getCode());
        tradePolicy.trade(createOrderAggregate);

        // 8. 返回订单信息，提取订单聚合对象中的订单信息并返回未支付订单实体
        ActivityOrderEntity activityOrderEntity = createOrderAggregate.getActivityOrderEntity();
        return UnpaidActivityOrderEntity.builder()
                .userId(userId)
                .orderId(activityOrderEntity.getOrderId())
                .outBusinessNo(activityOrderEntity.getOutBusinessNo())
                .payAmount(activityOrderEntity.getPayAmount())
                .build();
    }

    protected abstract CreateQuotaOrderAggregate buildOrderAggregate(SkuRechargeEntity skuRechargeEntity, ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity);

}
